package lingou.homework.postbar.controller;

import com.fasterxml.jackson.databind.JsonNode;
import jakarta.servlet.http.HttpSession;
import lingou.homework.postbar.controller.proto.MessageView;
import lingou.homework.postbar.controller.proto.PostView;
import lingou.homework.postbar.controller.proto.resp.Response;
import lingou.homework.postbar.controller.tool.SessionHelper;
import lingou.homework.postbar.controller.tool.Tools;
import lingou.homework.postbar.domain.*;
import lingou.homework.postbar.service.PostService;
import lingou.homework.postbar.service.UserService;
import lingou.homework.postbar.service.enums.UserTypeEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/post")
public class PostController {

    @Autowired
    PostService postService;
    @Autowired
    UserService userService;
    @Autowired
    MessageView messageView;
    @Autowired
    PostView postView;

    /**
     * 获取帖子内容
     * @param postId
     * @return
     */
    @GetMapping
    Response getContent(Long postId, Boolean meta, HttpSession session){
        long currentUser = SessionHelper.checkLogin(session);
        PostSnapshot lastPostSnapshot = postService.getContent(postId);
        if(meta == null) meta = false;
        if(meta) return Response.ofSuccess(postView.ofAnnoPost(postService.getPost(postId), currentUser));
        return Response.ofSuccess(Map.of(
                "content", lastPostSnapshot.getContent(),
                "time", lastPostSnapshot.getTime()));
    }

    @DeleteMapping
    Response deletePost(Long postId, HttpSession session){
        Long userId = SessionHelper.getCurrentUser(session);
        if(userId == null) return SessionHelper.NOT_LOGGED;
        Post post = postService.getPost(postId);
//        if(userId.equals(post.getUserId()) || userService.isManager(userId)) {
        if(userService.isManager(userId)) {
            postService.deletePost(postId);
            return Response.ofSuccess();
        }
        else return Response.NO_PERMISSION;
    }

    @GetMapping("/notice")
    Response getNoticePosts(Integer start, Integer count, Boolean getLength, HttpSession session){
        if(!SessionHelper.isLogin(session)) return SessionHelper.NOT_LOGGED;
        if(start == null) start = 0;
        if(getLength == null) getLength = false;
        List<Post> list = postService.getNoticePosts(start, count);
        if(getLength) return Response.ofSuccess(list.size());
        return Response.ofSuccess(list);
    }

    @PostMapping("/notice")
    Response postNotice(String title, @RequestBody String content, HttpSession session){
        long userId = SessionHelper.checkLogin(session);
        if(!userService.isManager(userId)) return Response.NO_PERMISSION;
        postService.postNotice(userId, title, content);
        return Response.SUCCESS;
    }

    @GetMapping("/news")
    Response getNewsPosts(Integer start, Integer count, Boolean getLength, HttpSession session){
        if(!SessionHelper.isLogin(session)) return SessionHelper.NOT_LOGGED;
        if(start == null) start = 0;
        if(getLength == null) getLength = false;
        List<Post> list = postService.getNewsPosts(start, count);
        if(getLength) return Response.ofSuccess(list.size());
        return Response.ofSuccess(list);
    }

    @PostMapping("/news")
    Response postNews(String title, @RequestBody String content, HttpSession session){
        Long userId = SessionHelper.getCurrentUser(session);
        if(userId == null) return SessionHelper.NOT_LOGGED;
        if(!userService.isManager(userId)) return Response.NO_PERMISSION;
        postService.postNews(userId, title, content);
        return Response.SUCCESS;
    }

    /**
     * 获取范围内公共帖子
     * @param start
     * @param count
     * @param tag
     * @param search
     * @return
     */
    @GetMapping("/public")
    Response getPublicPosts(Long userId, Integer start, Long count, Boolean getLength, long[] tag, String search, HttpSession session) {
        Long currentUser = SessionHelper.checkLogin(session);
        if(start == null) start = 0;
//        if(start < 0 || count < 0) return Response.ofFailure("格式错误");
        List<Post> list = postService.getPublicPosts(start, count, tag, search, userId, currentUser.equals(userId)).stream()
                    .map(post -> postView.ofAnnoPost(post, currentUser)).toList();
        if(getLength == null) getLength = false;
        if(getLength) return Response.ofSuccess(list.size());
        return Response.ofSuccess(list);
    }

    /**
     * 发布公共帖子
     * @param title
     * @param content
     * @param anonymous
     * @param draw
     * @return
     */
    @PostMapping("/public")
    Response publishPost(String title, Boolean anonymous, Boolean draw, @RequestBody String content, HttpSession session) {
        Long userId = SessionHelper.checkLogin(session);
        if(anonymous == null) anonymous = false;
        if(draw == null) draw = false;
        Post post = postService.publishPost(userId, title, content, anonymous, draw);
        return Response.ofSuccess(post);
    }

    @PutMapping("/public")
    Response modifyPost(Long postId, String title, @RequestBody String content, HttpSession session) {
        Response fail = SessionHelper.selfOperation(session, postService.getPost(postId));
        if(fail != null) return fail;
        postService.modifyPost(postId, title, content);
        return Response.ofSuccess();
    }

    @PutMapping("/public/draw")
    Response setDrawPost(Long postId, Boolean draw, HttpSession session) {
        Response fail = SessionHelper.selfOperation(session, postService.getPost(postId));
        if(fail != null) return fail;
        if(!postService.isPublicPost(postId)) return Response.ofFailure("非公共帖子无法设置为草稿");
        postService.setPostDraw(postId, draw);
        return Response.ofSuccess();
    }

    @PutMapping("/public/type")
    Response setPostTags(Long postId, long[] tag, HttpSession session){
        long userId = SessionHelper.checkLogin(session);
        postService.setTags(userId, postId, tag);
        return Response.ofSuccess();
    }

    @GetMapping("/public/type")
    Response getPostTags(Long postId, HttpSession session) {
        long userId = SessionHelper.checkLogin(session);
        List<Tag> tags = postService.getTags(userId, postId);
        return Response.ofSuccess(tags);
    }

    @GetMapping("/types")
    Response getAllTag(){
        return Response.ofSuccess(postService.getAllPostTags());
    }

    /**
     * 回复
     * @param postId
     * @param content
     * @return
     */
    @PostMapping("/reply")
    Response reply(Long postId, Long atUserId, Boolean anno, @RequestBody String content, HttpSession session) {
        Long userId = SessionHelper.getCurrentUser(session);
        if(userId == null) return SessionHelper.NOT_LOGGED;
        if(anno == null) anno = false;
        postService.reply(postId, userId, content, anno, atUserId);
        return Response.ofSuccess();
    }

    @GetMapping("/reply/count")
    Response getReplyCount(Long postId, HttpSession session){
        Long currentUser = SessionHelper.getCurrentUser(session);
        if(currentUser == null) return SessionHelper.NOT_LOGGED;
        List<Post> allReply = postService.getAllReply(postId);
        return Response.ofSuccess(allReply.size());
    }

    @GetMapping("/reply")
    Response getReplyPosts(Long postId, HttpSession session){
        Long currentUser = SessionHelper.getCurrentUser(session);
        if(currentUser == null) return SessionHelper.NOT_LOGGED;
        List<Post> allReply = postService.getAllReply(postId);
        allReply = allReply.stream().map(child -> {
            if(!currentUser.equals(child.getPostId()))
                child = postView.ofAnnoPost(child, currentUser);
            return child;
        }).toList();
        return Response.ofSuccess(allReply);
    }

    @GetMapping("/question/count")
    Response getBoxPostCount(Long userId, HttpSession session){
        Long currentUser = SessionHelper.getCurrentUser(session);
        if(currentUser == null) return SessionHelper.NOT_LOGGED;
        if(userId == null) userId = currentUser;
        boolean self = currentUser.equals(userId);
        return Response.ofSuccess(postService.getBoxPostCount(userId, !self));
    }

    @GetMapping("/question/owner")
    Response getBoxOwner(long postId, HttpSession session) {
        SessionHelper.checkLogin(session);
        long boxOwner = postService.getBoxOwner(postId);
        return Response.ofSuccess(userService.getUser(boxOwner));
    }

    /**
     * 获取提问箱帖子
     * @param userId
     * @param start
     * @param count
     * @return
     */
    @GetMapping("/question")
    Response getBoxPosts(Long userId, Integer start, Long count, Boolean getLength, Boolean hasAnswer, Boolean mine, HttpSession session) {
        Long currentUser = SessionHelper.getCurrentUser(session);
        if(currentUser == null) return SessionHelper.NOT_LOGGED;
        if(userId == null) userId = currentUser;
        boolean self = currentUser.equals(userId);
        if(start == null) start = 0;
        if(mine == null) mine = false;
        if(getLength == null) getLength = false;
        List<Post> boxPosts;
        if(mine) {
            boxPosts = postService.getBoxPosts(userId, false, hasAnswer, 0, null).stream()
                    .filter(post -> currentUser.equals(post.getUserId())).toList();
        }
        else {
            boxPosts = postService.getBoxPosts(userId, !self, hasAnswer, start, count).stream()
                    .map(post -> postView.ofAnnoPost(post, currentUser)).toList();
        }
        List<JsonNode> r = boxPosts.stream().map(post -> postView.ofPubBoxPost(post, currentUser)).toList();
        return Response.ofSuccess(getLength ? r.size() : r);
    }

    @GetMapping("/question/my")
    Response getMyQuestion(Boolean hasAnswer, HttpSession session){
        Long currentUser = SessionHelper.getCurrentUser(session);
        if(currentUser == null) return SessionHelper.NOT_LOGGED;
        List<Post> boxPosts = postService.getBoxPosts(null, false, hasAnswer, 0, null).stream()
                .filter(post -> currentUser.equals(post.getUserId())).toList();
        List<JsonNode> r = boxPosts.stream().map(post -> postView.ofPubBoxPost(post, currentUser)).toList();
        return Response.ofSuccess(r);
    }

    /**
     * 提问
     * @param userId
     * @param title
     * @param content
     * @return
     */
    @PostMapping("/question")
    Response postQuestion(Long userId, String title, @RequestBody String content, HttpSession session) {
        Long currentUser = SessionHelper.getCurrentUser(session);
        if(currentUser == null) return SessionHelper.NOT_LOGGED;
        postService.postQuestion(currentUser, userId, title, content);
        return Response.ofSuccess();
    }


    /**
     * 回答
     * @param postId
     * @param content
     * @param pub
     * @return
     */
    @PostMapping("/answer")
    Response postAnswer(Long postId, Boolean pub, @RequestBody String content, HttpSession session) {
        Long currentUser = SessionHelper.getCurrentUser(session);
        if(currentUser == null) return SessionHelper.NOT_LOGGED;
        if(pub == null) pub = false;
        postService.replyBoxPost(currentUser, postId, content, pub);
        return Response.ofSuccess();
    }

    @PutMapping("/answer/pub")
    Response pubAnswer(Long postId, Boolean pub, HttpSession session) {
        Long currentUser = SessionHelper.getCurrentUser(session);
        if(currentUser == null) return SessionHelper.NOT_LOGGED;
        if(pub == null) pub = true;
        if(!postService.setPubAnswer(currentUser, postId, pub)) return Response.NO_PERMISSION;
        return Response.ofSuccess();
    }

    @GetMapping("/answer/pub")
    Response isQuestionPub(Long postId, HttpSession session){
        Long currentUser = SessionHelper.getCurrentUser(session);
        if(currentUser == null) return SessionHelper.NOT_LOGGED;
        if(postId == null) return Response.UNCOMPLETED;
        return Response.ofSuccess(postService.isBoxPostPub(currentUser, postId));
    }

    /**
     * 点赞
     * @param postId
     * @return
     */
    @PutMapping("/like")
    Response likePost(Long postId, HttpSession session) {
        Long currentUser = SessionHelper.getCurrentUser(session);
        if(currentUser == null) return SessionHelper.NOT_LOGGED;
        if(postId == null) return Response.UNCOMPLETED;
        postService.opLikePost(currentUser, postId, false, 0);
        return Response.ofSuccess(true);
    }

    /**
     * 撤销点赞
     * @param postId
     * @return
     */
    @DeleteMapping("/like")
    Response undoLikePost(Long postId, HttpSession session) {
        Long currentUser = SessionHelper.getCurrentUser(session);
        if(currentUser == null) return SessionHelper.NOT_LOGGED;
        if(postId == null) return Response.UNCOMPLETED;
        postService.opLikePost(currentUser, postId, true, 0);
        return Response.ofSuccess(true);
    }

    /**
     * 当前用户是否已经点赞
     * @param postId
     * @return
     */
    @GetMapping("/like")
    Response hasLikedPost(Long postId, HttpSession session) {
        Long currentUser = SessionHelper.getCurrentUser(session);
        if(currentUser == null) return SessionHelper.NOT_LOGGED;
        if(postId == null) return Response.UNCOMPLETED;
        return Response.ofSuccess(postService.isOpLiked(currentUser, postId, 0));
    }

    /**
     * 点踩
     * @param postId
     * @return
     */
    @PutMapping("/dislike")
    Response dislikePost(Long postId, HttpSession session) {
        Long currentUser = SessionHelper.getCurrentUser(session);
        if(currentUser == null) return SessionHelper.NOT_LOGGED;
        if(postId == null) return Response.UNCOMPLETED;
        postService.opLikePost(currentUser, postId, false, 1);
        return Response.ofSuccess(true);
    }

    /**
     * 撤销点踩
     * @param postId
     * @return
     */
    @DeleteMapping("/dislike")
    Response undoDislikePost(Long postId, HttpSession session) {
        Long currentUser = SessionHelper.getCurrentUser(session);
        if(currentUser == null) return SessionHelper.NOT_LOGGED;
        if(postId == null) return Response.UNCOMPLETED;
        postService.opLikePost(currentUser, postId, true, 1);
        return Response.ofSuccess(true);
    }

    /**
     * 当前用户是否已经点踩
     * @param postId
     * @return
     */
    @GetMapping ("/dislike")
    Response hasDislikedPost(Long postId, HttpSession session) {
        Long currentUser = SessionHelper.getCurrentUser(session);
        if(currentUser == null) return SessionHelper.NOT_LOGGED;
        if(postId == null) return Response.UNCOMPLETED;
        return Response.ofSuccess(postService.isOpLiked(currentUser, postId, 1));
    }

    /**
     * 获取消息列表
     * @return
     */
    @GetMapping("/message")
    Response getMessagePost(Integer start, Integer count, Boolean getLength, Boolean unread, HttpSession session){
        Long currentUser = SessionHelper.getCurrentUser(session);
        if(currentUser == null) return SessionHelper.NOT_LOGGED;
        if(start == null) start = 0;
        if(unread == null) unread = false;
        if(getLength == null) getLength = false;
        List<Message> messages = postService.getMessages(start, count, unread, currentUser);
        List<? extends JsonNode> list = Tools.mapList(messages, messageView::expand);
        return Response.ofSuccess(getLength ? list.size() : list);
    }

    @PutMapping("/message/read")
    Response readMessage(Long messageId, HttpSession session){
        long currentUser = SessionHelper.checkLogin(session);
        if(messageId == null) postService.readAllMessages(currentUser);
        else postService.readMessage(currentUser, messageId);
        return Response.ofSuccess();
    }

}
